package com.zlsy.secondtime.deadlock;

import java.util.Random;

/**
 * @author zhouliang
 * @date 2020/6/19 20:11
 * <p>
 * 哲学家就餐造成的死锁问题解决：通过最后一个哲学家换手解决。
 */
public class SolvePhilosophersProblemsByChangingHands {

    static class SolvePhilosopher implements Runnable {
        private final Object leftChopsticks;
        private final Object rightChopsticks;

        public SolvePhilosopher(Object leftChopsticks, Object rightChopsticks) {
            this.leftChopsticks = leftChopsticks;
            this.rightChopsticks = rightChopsticks;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    doAction("Thinking");
                    synchronized (leftChopsticks) {
                        doAction("Picked up left Chopsticks");
                        synchronized (rightChopsticks) {
                            doAction("Picked up right Chopsticks - eating");
                            doAction("Put down right Chopsticks");
                        }
                        doAction("Put down left Chopsticks");
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void doAction(String action) throws InterruptedException {
            System.out.println(Thread.currentThread().getName() + "" + action);
            Thread.sleep(Integer.valueOf(new Random().nextInt(10)).longValue());
        }
    }

    public static void main(String[] args) {
        SolvePhilosophersProblemsByChangingHands[] philosophers = new SolvePhilosophersProblemsByChangingHands[5];
        Object[] chopsticks = new Object[philosophers.length];
        for (int i = 0; i < chopsticks.length; i++) {
            chopsticks[i] = new Object();
        }
        for (int i = 0; i < philosophers.length; i++) {
            Object leftChopsticks = chopsticks[i];
            Object rightChopsticks = chopsticks[(i + 1) % chopsticks.length];
            //拿到筷子
            SolvePhilosopher solvePhilosopher = null;
            //如果是最后一个人则先拿右边的
            if (i == philosophers.length - 1) {
                solvePhilosopher = new SolvePhilosopher(rightChopsticks, leftChopsticks);
            } else {
                solvePhilosopher = new SolvePhilosopher(leftChopsticks, rightChopsticks);
            }

            Thread thread = new Thread(solvePhilosopher, "哲学家" + (i + 1) + "号");
            thread.start();
        }
    }
}
